"""
Error handling middleware for standardized error responses
"""
import logging
import traceback
import time
from typing import Dict, Any
from fastapi import Request, Response, HTTPException
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
from pydantic import ValidationError

logger = logging.getLogger(__name__)


class ErrorHandlerMiddleware(BaseHTTPMiddleware):
    """
    Middleware to handle errors and return standardized error responses
    """
    
    def __init__(self, app, debug: bool = False):
        super().__init__(app)
        self.debug = debug
    
    async def dispatch(self, request: Request, call_next):
        try:
            response = await call_next(request)
            return response
        
        except HTTPException as exc:
            return await self._handle_http_exception(request, exc)
        
        except ValidationError as exc:
            return await self._handle_validation_error(request, exc)
        
        except Exception as exc:
            return await self._handle_general_exception(request, exc)
    
    async def _handle_http_exception(self, request: Request, exc: HTTPException) -> JSONResponse:
        """Handle FastAPI HTTP exceptions"""
        error_data = {
            "error": {
                "type": "http_error",
                "message": exc.detail,
                "status_code": exc.status_code,
                "path": str(request.url.path),
                "method": request.method,
                "timestamp": time.time()
            }
        }
        
        # Add debug information if in debug mode
        if self.debug and hasattr(exc, "headers"):
            error_data["debug"] = {
                "headers": dict(exc.headers) if exc.headers else None
            }
        
        logger.warning(f"HTTP {exc.status_code} error at {request.url.path}: {exc.detail}")
        
        return JSONResponse(
            status_code=exc.status_code,
            content=error_data
        )
    
    async def _handle_validation_error(self, request: Request, exc: ValidationError) -> JSONResponse:
        """Handle Pydantic validation errors"""
        error_details = []
        for error in exc.errors():
            error_details.append({
                "field": " -> ".join(str(loc) for loc in error["loc"]),
                "message": error["msg"],
                "type": error["type"]
            })
        
        error_data = {
            "error": {
                "type": "validation_error",
                "message": "Request validation failed",
                "details": error_details,
                "status_code": 422,
                "path": str(request.url.path),
                "method": request.method,
                "timestamp": time.time()
            }
        }
        
        logger.error(f"Validation error at {request.url.path}: {error_details}")
        
        return JSONResponse(
            status_code=422,
            content=error_data
        )
    
    async def _handle_general_exception(self, request: Request, exc: Exception) -> JSONResponse:
        """Handle all other exceptions"""
        error_id = f"err_{int(time.time())}_{id(exc)}"
        
        error_data = {
            "error": {
                "type": "internal_error",
                "message": "An internal server error occurred",
                "error_id": error_id,
                "status_code": 500,
                "path": str(request.url.path),
                "method": request.method,
                "timestamp": time.time()
            }
        }
        
        # Add debug information if in debug mode
        if self.debug:
            error_data["debug"] = {
                "exception_type": type(exc).__name__,
                "exception_message": str(exc),
                "traceback": traceback.format_exc()
            }
        
        logger.error(f"Unhandled exception [{error_id}] at {request.url.path}: {str(exc)}", exc_info=True)
        
        return JSONResponse(
            status_code=500,
            content=error_data
        )


def error_handler_middleware(debug: bool = False):
    """Factory function to create error handler middleware"""
    def create_middleware(app):
        return ErrorHandlerMiddleware(app, debug=debug)
    return create_middleware